﻿using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;

namespace WP7Contrib.View.Controls
{
    /// <summary>
    /// web browser control to allow for adding in application browsing.  By design this is a control not a page,
    /// so you can customize the underlying page including transitions and custom application bar customizations. all buttons
    /// and menu items will be added after any customizations to the underlying page
    /// </summary>
    public class ApplicationBrowser : Grid
    {
        #region fields

        // embeded browser
        WebBrowser _browser;

        #endregion

        #region properties


        #region LoadingVisibility (DependencyProperty)

        /// <summary>
        /// visibility which can be bound to to set loading text
        /// </summary>
        public Visibility LoadingVisibility
        {
            get { return (Visibility)GetValue(LoadingVisibilityProperty); }
            private set { SetValue(LoadingVisibilityProperty, value); }
        }
        public static readonly DependencyProperty LoadingVisibilityProperty =
            DependencyProperty.Register("LoadingVisibility", typeof(Visibility), typeof(ApplicationBrowser),
              new PropertyMetadata(Visibility.Collapsed));

        #endregion
        

        #region IsLoading (DependencyProperty)

        /// <summary>
        /// is the browser control loading
        /// </summary>
        public bool IsLoading
        {
            get { return (bool)GetValue(IsLoadingProperty); }
            private set 
            { 
                SetValue(IsLoadingProperty, value); 
            }
        }
        public static readonly DependencyProperty IsLoadingProperty =
            DependencyProperty.Register("IsLoading", typeof(bool), typeof(ApplicationBrowser),
              new PropertyMetadata(false));

        #endregion
        

        #region ShareEmailText (DependencyProperty)

        /// <summary>
        /// Share by email text
        /// </summary>
        public string ShareEmailText
        {
            get { return (string)GetValue(ShareEmailTextProperty); }
            set { SetValue(ShareEmailTextProperty, value); }
        }
        public static readonly DependencyProperty ShareEmailTextProperty =
            DependencyProperty.Register("ShareEmailText", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata("Share by Email"));

        #endregion


        #region ShareSmsText (DependencyProperty)

        /// <summary>
        /// text to show on share by sms item
        /// </summary>
        public string ShareSmsText
        {
            get { return (string)GetValue(ShareSmsTextProperty); }
            set { SetValue(ShareSmsTextProperty, value); }
        }
        public static readonly DependencyProperty ShareSmsTextProperty =
            DependencyProperty.Register("ShareSmsText", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata("Share by Text"));

        #endregion


        #region OpenBrowserText (DependencyProperty)

        /// <summary>
        /// text to show on the open browser item
        /// </summary>
        public string OpenBrowserText
        {
            get { return (string)GetValue(OpenBrowserTextProperty); }
            set { SetValue(OpenBrowserTextProperty, value); }
        }
        public static readonly DependencyProperty OpenBrowserTextProperty =
            DependencyProperty.Register("OpenBrowserText", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata("View in Internet Explorer"));

        #endregion


        #region SharePrefixText (DependencyProperty)

        /// <summary>
        /// text to show as a prefix to the sms or email share
        /// </summary>
        public string SharePrefixText
        {
            get { return (string)GetValue(SharePrefixTextProperty); }
            set { SetValue(SharePrefixTextProperty, value); }
        }
        public static readonly DependencyProperty SharePrefixTextProperty =
            DependencyProperty.Register("SharePrefixText", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata(string.Empty));

        #endregion
        

        #region RefreshText (DependencyProperty)

        /// <summary>
        /// text to show on the refresh button
        /// </summary>
        public string RefreshText
        {
            get { return (string)GetValue(RefreshTextProperty); }
            set { SetValue(RefreshTextProperty, value); }
        }
        public static readonly DependencyProperty RefreshTextProperty =
            DependencyProperty.Register("RefreshText", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata("Refresh"));

        #endregion


        #region Uri (DependencyProperty)

        /// <summary>
        /// uri for the browser
        /// </summary>
        public string Uri
        {
            get { return (string)GetValue(UriProperty); }
            set { SetValue(UriProperty, value); }
        }
        public static readonly DependencyProperty UriProperty =
            DependencyProperty.Register("Uri", typeof(string), typeof(ApplicationBrowser),
            new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnUriChanged)));

        private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ApplicationBrowser)d).OnUriChanged(e);
        }

        protected virtual void OnUriChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue.ToString() != string.Empty)
            {
                if (_browser == null)
                {
                    Load();
                    _browser.Loaded += new RoutedEventHandler(_browser_Loaded);
                }
                else
                {
                    _browser.Navigate(new Uri(Uri));
                }
            }
        }

        void _browser_Loaded(object sender, RoutedEventArgs e)
        {
            _browser.Loaded -= _browser_Loaded;
            _browser.Navigate(new Uri(Uri));
        }

        #endregion


        #region RefreshIcon (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public string RefreshIcon
        {
            get { return (string)GetValue(RefreshIconProperty); }
            set { SetValue(RefreshIconProperty, value); }
        }
        public static readonly DependencyProperty RefreshIconProperty =
            DependencyProperty.Register("RefreshIcon", typeof(string), typeof(ApplicationBrowser),
              new PropertyMetadata("/icons/appbar.refresh.rest.png"));

        #endregion

        #endregion

        #region inits
        public override void OnApplyTemplate()
        {
            this.Loaded += new RoutedEventHandler(ApplicationBrowser_Loaded);
            base.OnApplyTemplate();
        }
        #endregion

        #region tombstone the uri
        void ApplicationBrowser_Loaded(object sender, RoutedEventArgs e)
        {
            PhoneApplicationService.Current.Deactivated -= Current_Deactivated;
            PhoneApplicationService.Current.Activated -= Current_Activated;
            PhoneApplicationService.Current.Deactivated += new EventHandler<DeactivatedEventArgs>(Current_Deactivated);
            PhoneApplicationService.Current.Activated += new EventHandler<ActivatedEventArgs>(Current_Activated);
        }

        void Current_Activated(object sender, ActivatedEventArgs e)
        {
            if (PhoneApplicationService.Current.State.ContainsKey("inbrowseruri"))
            {
                Uri = PhoneApplicationService.Current.State["inbrowseruri"].ToString();
            }
        }

        void Current_Deactivated(object sender, DeactivatedEventArgs e)
        {
            PhoneApplicationService.Current.State["inbrowseruri"] = Uri;

        }
        #endregion

        /// <summary>
        /// load the browser control, and set up the app bar
        /// </summary>
        private void Load()
        {
            PhoneApplicationFrame frame = (PhoneApplicationFrame)Application.Current.RootVisual;
            PhoneApplicationPage page = (PhoneApplicationPage)frame.Content;
            ApplicationBar bar = null;
            if (page.ApplicationBar != null)
            {
                bar = (ApplicationBar)page.ApplicationBar;
            }
            else
            {
                page.ApplicationBar = new ApplicationBar();
                bar = (ApplicationBar) page.ApplicationBar;
            }

            bool foundbtn = false;
           
            foreach (IApplicationBarIconButton btn in page.ApplicationBar.Buttons)
            {
                if (btn.Text.ToLower() == RefreshText.ToLower())
                {
                    foundbtn = true;
                    break;
                }
            }

            if (!foundbtn)
            {
                ApplicationBarIconButton btn = new ApplicationBarIconButton();
                btn.Text = RefreshText;
                btn.Click += new EventHandler(RefreshButton_Click);
                btn.IconUri = new System.Uri(RefreshIcon, UriKind.RelativeOrAbsolute);
                bar.Buttons.Add(btn);
            }

            bool openFound = false;
            bool shareSms = false;
            bool shareMail = false;
            foreach (IApplicationBarMenuItem item in page.ApplicationBar.MenuItems)
            {
                if (item.Text.ToLower() == OpenBrowserText.ToLower())
                {
                    openFound = true;
                }
                else if (item.Text.ToLower() == ShareEmailText.ToLower())
                {
                    shareMail = true;
                }
                else if (item.Text.ToLower() == ShareSmsText.ToLower())
                {
                    shareSms = true;
                }
            }



            if (!openFound)
            {
                ApplicationBarMenuItem item = new ApplicationBarMenuItem();
                item.Text = OpenBrowserText;
                item.Click += new EventHandler(IEItem_Click);
                bar.MenuItems.Add(item);
            }

            if (!shareMail)
            {
                ApplicationBarMenuItem itemShareMail = new ApplicationBarMenuItem();
                itemShareMail.Text = ShareEmailText;
                itemShareMail.Click += new EventHandler(itemShareMail_Click);
                bar.MenuItems.Add(itemShareMail);
            }

            if (!shareSms)
            {
                ApplicationBarMenuItem itemShareSms = new ApplicationBarMenuItem();
                itemShareSms.Text = ShareSmsText;
                itemShareSms.Click += new EventHandler(itemShareSms_Click);
                bar.MenuItems.Add(itemShareSms);
            }

            if (this.Children.Count == 0 || this.Children[0].GetType() != typeof(WebBrowser))
            {
                this.Children.Clear();
                _browser = new WebBrowser();
                _browser.IsScriptEnabled = true;
                _browser.Navigating += new EventHandler<NavigatingEventArgs>(_browser_Navigating);
                _browser.Navigated += new EventHandler<System.Windows.Navigation.NavigationEventArgs>(_browser_Navigated);

                this.Children.Add(_browser);
            }

        }

        /// <summary>
        /// done loading
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            IsLoading = false;
            LoadingVisibility = System.Windows.Visibility.Collapsed;
        }

        /// <summary>
        /// browser is navigation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _browser_Navigating(object sender, NavigatingEventArgs e)
        {
            IsLoading = true;
            LoadingVisibility = System.Windows.Visibility.Visible;

        }

        #region browser interaction
        /// <summary>
        /// share by sms
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void itemShareSms_Click(object sender, EventArgs e)
        {
            SmsComposeTask task = new SmsComposeTask();

            if (SharePrefixText != string.Empty)
                task.Body = string.Format("{0} {1}", SharePrefixText, _browser.Source.ToString());
            else
                task.Body = _browser.Source.ToString();

            task.Show();
        }

        /// <summary>
        /// share by email
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void itemShareMail_Click(object sender, EventArgs e)
        {
            EmailComposeTask task = new EmailComposeTask();
            if (SharePrefixText != string.Empty)
                task.Body = string.Format("{0} {1}", SharePrefixText, _browser.Source.ToString());
            else
                task.Body = _browser.Source.ToString();
            task.Show();
        }


        /// <summary>
        /// open ie
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void IEItem_Click(object sender, EventArgs e)
        {
            var task = new WebBrowserTask {Uri = new Uri(Uri)};
            task.Show();
        }

        /// <summary>
        /// refresh the browser
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void RefreshButton_Click(object sender, EventArgs e)
        {
            _browser.Navigate(_browser.Source);
        }

        #endregion
    }
}
